package ninja.awesome.game;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import ninja.awesome.framework.Game;
import ninja.awesome.framework.Graphics;
import ninja.awesome.framework.Input.TouchEvent;
import ninja.awesome.framework.Screen;
import ninja.awesome.framework.control.GameButton;
import ninja.awesome.framework.control.GameButton.ButtonListener;
import ninja.awesome.framework.impl.AndroidGame;
import ninja.awesome.game.classes.Friendly;
import ninja.awesome.game.classes.Hostile;
import ninja.awesome.game.compat.KeyEvent;
import ninja.awesome.game.gameobject.Attack;
import ninja.awesome.game.gameobject.Building;
import ninja.awesome.game.gameobject.Bush;
import ninja.awesome.game.gameobject.Health;
import ninja.awesome.game.gameobject.MyNinja;
import ninja.awesome.game.gameobject.Road;
import ninja.awesome.game.gameobject.ScoreBoard;
import ninja.awesome.game.gameobject.Tree;
import ninja.awesome.game.main.Controller;
import ninja.awesome.game.main.Sprites;
import ninja.awesome.game.main.Timeline;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;

public class MainGameScreen extends Screen implements ButtonListener {

	private static final int SPEED_X = 8;
	private static final int BUTTON_SIZE = 100;
	// FIELDS
	private static final long serialVersionUID = 1L;
	public static final int WIDTH = 1280;
	public static final int HEIGHT = 720;
	public static final int SCALE = 2;
	public final String TITLE = "Ninja Awesome";

	private boolean running = true;
	private boolean slashing = false;
	private boolean jumping = false;
	private boolean bossSpawn = false;
	private boolean win = false;
	private boolean gameOver = false;
	private boolean throwing = false;
	private boolean weapon = true;

	private int ticks = 0, level;
	private int move = 0, speed = 1;
	private int enemy_count = 2;
	private int enemy_killed = 0;
	private int totalKilled = 0;

	private int combo = 0, attackTimer = 0;
	private boolean enemy_spawn = false;
	private boolean building_Block = false;
	private boolean road_Block = false;
	private boolean tree_Block = false;
	private int road_Distance = 1057;
	private Timeline time;

	public LinkedList<Friendly> fl;
	public LinkedList<Hostile> hl;
	public LinkedList<Building> bl;
	public LinkedList<Bush> bushL;
	public LinkedList<Road> rl;
	public LinkedList<Tree> tree;

	// GAME OBJECTS
	private MyNinja mp;
	private MyNinja mp2;
	private Health currentHealthBar;
	private MyNinja currentDamagetaken;
	// private weapons weapons;
	private Controller c;
	private ScoreBoard sb;
	// private Background gb;
	private Sprites s;

	GameButton mUp, mDown, mLeft, mRigth;
	GameButton mShot, mJump, mSlash;
	List<GameButton> buttons = new ArrayList<GameButton>();

	private GameButton getMenuButton(String text, int x, int y, int width, int height) {
		GameButton result = new GameButton(game);
		result.setText(text);
		result.setTextColor(Color.WHITE);
		result.setBackgroundColor(Color.argb(120, 100, 100, 100));
		result.setTextSize(25);
		result.setPosition(x, y, width, height);
		result.setButtonListener(this);
		return result;
	}

	private void initControlButtons() {
		mUp = getMenuButton("UP", 200, 440, BUTTON_SIZE, BUTTON_SIZE);
		mUp.setKeyCode(KeyEvent.VK_W);
		mUp.setBackgroundImage(Assets.btnUp);
		mUp.setPressedImage(Assets.btnUpPressed);
		mDown = getMenuButton("DOWN", 200, 600, BUTTON_SIZE, BUTTON_SIZE);
		mDown.setKeyCode(KeyEvent.VK_S);
		mDown.setBackgroundImage(Assets.btnDown);
		mDown.setPressedImage(Assets.btnDownPressed);
		mLeft = getMenuButton("LEFT", 120, 520, BUTTON_SIZE, BUTTON_SIZE);
		mLeft.setKeyCode(KeyEvent.VK_A);
		mLeft.setBackgroundImage(Assets.btnLeft);
		mLeft.setPressedImage(Assets.btnLeftPressed);
		mRigth = getMenuButton("RIGHT", 280, 520, BUTTON_SIZE, BUTTON_SIZE);
		mRigth.setKeyCode(KeyEvent.VK_D);
		mRigth.setBackgroundImage(Assets.btnRight);
		mRigth.setPressedImage(Assets.btnRightPressed);

		mShot = getMenuButton("SHOT", 1020, 480, BUTTON_SIZE, BUTTON_SIZE);
		mShot.setKeyCode(KeyEvent.VK_I);
		mShot.setBackgroundImage(Assets.btnShot);
		mShot.setPressedImage(Assets.btnShotPressed);
		mJump = getMenuButton("JUMP", 1020, 600, BUTTON_SIZE, BUTTON_SIZE);
		mJump.setBackgroundImage(Assets.btnJump);
		mJump.setPressedImage(Assets.btnJumpPressed);
		mJump.setKeyCode(KeyEvent.VK_SPACE);
		mSlash = getMenuButton("SLASH", 900, 530, BUTTON_SIZE, BUTTON_SIZE);
		mSlash.setKeyCode(KeyEvent.VK_J);
		mSlash.setBackgroundImage(Assets.btnSlash);
		mSlash.setPressedImage(Assets.btnSlashPressed);

		buttons.add(mUp);
		buttons.add(mDown);
		buttons.add(mLeft);
		buttons.add(mRigth);
		buttons.add(mShot);
		buttons.add(mJump);
		buttons.add(mSlash);
	}

	public static enum PlayingMode {
		SINGLE, MULTIPLE
	}

	private PlayingMode mode = PlayingMode.SINGLE;
	private String playerName;

	public PlayingMode getPlayingMode() {
		return mode;
	}

	public MainGameScreen(Game game) {
		super(game);
		init();
	}

	public void init() {
		initControlButtons();

		s = new Sprites(this);
		c = new Controller(this, s);
		sb = new ScoreBoard(30, 5, 3, 0, this, s);
		mp = new MyNinja(WIDTH / 2, HEIGHT - 300, this, c, s);
		sb.setNinja(mp);
		// weapons = new weapons(mp.getX()+10,mp.getY(), mp
		// .getDirection(), this, c, s, 2);
		currentHealthBar = new Health(0, 0, this, c, s);

		// c.spawnEnemy(enemy_count);
		// c.spawnEnemy1(enemy_count);
		c.spawnBuilding(0);// I added for building from Jung
		c.spawnRoad(0);
		c.spawnBush(0);
		c.spawnTree(0);
		fl = c.getFriendly();
		hl = c.getHostile();
		bl = c.getBuilding();
		rl = c.getRoad();
		tree = c.getTree1();
		tree = c.getTree2();

		level = 1; // define the level of the game. We MUST remove this
		// when we go to production
		time = new Timeline(level);

	}

	public void keyPressed(KeyEvent e) {

		int key = e.getKeyCode();
		if (getPlayingMode() == PlayingMode.SINGLE) {
			if (key == KeyEvent.VK_D) {
				mp.setSpeedX(SPEED_X);
				mp.setIsRunning(true);
				mp.setDirection("right");
			} else if (key == KeyEvent.VK_A) {
				mp.setSpeedX(-SPEED_X);
				mp.setIsRunning(true);
				mp.setDirection("left");
			}
			if (key == KeyEvent.VK_S && !jumping) {
				mp.setSpeedY(6);

			}
			if (key == KeyEvent.VK_W && !jumping) {
				mp.setSpeedY(-6);
			}
			if (key == KeyEvent.VK_SPACE) {
				jumping = true;
				mp.setIsJumping(true);
				mp.setSpeedY(0);
			}
			if (key == KeyEvent.VK_I)
				c.addFriendly(new Attack(mp.getX() + 80, mp.getY() + 90, mp.getDirection(), this, c, s, -1, 1));
		}

		if (key == KeyEvent.VK_I && !throwing)
			mp.setIsThrowing(true);

		if (key == KeyEvent.VK_J && !weapon) {
			weapon = true;
			mp.setIsAttacking(true);
		}

		if (key == KeyEvent.VK_J && !slashing) {
			slashing = true;
			mp.setIsAttacking(true);

			/*
			 * if (mp.isPowerup()) { c.addFriendly(new Attack(mp.getX() + 16,
			 * mp.getY() - 5, 's', this, c, s, combo)); c.addFriendly(new
			 * Attack(mp.getX() + 16, mp.getY() - 5, 'r', this, c, s, combo));
			 * c.addFriendly(new Attack(mp.getX(), mp.getY() - 5, 'l', this, c,
			 * s, combo)); combo++; if (combo > 4) { combo = 0; } }
			 */
			if (!mp.isPowerup()) {
				if (mp.getDirection().equals("right"))
					c.addFriendly(new Attack(mp.getX() + 10, mp.getY(), "right", this, c, s, combo, 0));
				else
					c.addFriendly(new Attack(mp.getX() - 85, mp.getY(), "left", this, c, s, combo, 0));
				combo++;
				if (combo > 4) {
					combo = 0;
				}
			}
		}
		if (key == KeyEvent.VK_E) {
			mp.setIsOpening(true);
		}

	}

	public void keyReleased(KeyEvent e) {

		int key = e.getKeyCode();
		if (getPlayingMode() == PlayingMode.SINGLE) {
			if (key == KeyEvent.VK_D) {
				mp.setIsRunning(false);
				mp.setSpeedX(0);

			} else if (key == KeyEvent.VK_A) {
				mp.setIsRunning(false);
				mp.setSpeedX(0);

			} else if (key == KeyEvent.VK_S) {
				mp.setSpeedY(0);
			} else if (key == KeyEvent.VK_W) {
				mp.setSpeedY(0);
			} else if (key == KeyEvent.VK_J) {
				slashing = false;
				mp.setIsAttacking(false);

			} else if (key == KeyEvent.VK_I) {
				mp.setIsThrowing(false);

			} else if (key == KeyEvent.VK_E) {
				mp.setIsOpening(false);

			} else if (key == KeyEvent.VK_SPACE) {

			}

		}

	}

	@Override
	public void update(float deltaTime) {
		if (!gameOver) {
			if (getPlayingMode() == PlayingMode.SINGLE) { // where the game
				c.update();
				sb.update();
				mp.update();
				time.run(c, this, ticks, bossSpawn, totalKilled);
			}
			if (mp.isAttacking()) {
				attackTimer++;
				if (attackTimer > 6) { // 6 is tha timer. Set it higher for a
										// longer time on the attack animation
					attackTimer = 0;
					mp.setIsAttacking(false);
				}
			}
			ticks++;
			List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
			for (GameButton b : buttons) {
				b.update(deltaTime, touchEvents);
			}
		}

		if (time.isWin() || mp.getRemainingLives() == 0) {
			NinjaGame _game = (NinjaGame) game;
			SharedPreferences preferences = _game.getSharedPreferences(NinjaGame.PREF_HIGH_SCORE, Context.MODE_APPEND);
			String scores = preferences.getString(NinjaGame.PREF_HIGH_SCORE_ARRAY, "[]");
			try {
				JSONArray arr = new JSONArray(scores);
				JSONArray newArr = new JSONArray();
				JSONObject newScore = new JSONObject();
				newScore.put("id", playerName);
				newScore.put("scores", mp.getScore());
				List<JSONObject> objs = new ArrayList<JSONObject>();
				for (int i = 0; i < arr.length(); ++i) {
					objs.add(arr.getJSONObject(i));
				}
				if (objs.size() == 0) {
					newArr.put(newScore);
				} else {
					objs.add(newScore);
					Collections.sort(objs, new Comparator<JSONObject>() {

						@Override
						public int compare(JSONObject lhs, JSONObject rhs) {
							try {
								return rhs.getInt("scores") - lhs.getInt("scores");
							} catch (Exception ex) {
								return 0;
							}
						}
					});
					for (int i = 0; i < (objs.size() < 5 ? objs.size() : 5); ++i) {
						newArr.put(objs.get(i));
					}
				}
				preferences.edit().putString(NinjaGame.PREF_HIGH_SCORE_ARRAY, newArr.toString()).commit();
			} catch (JSONException e) {
				e.printStackTrace();
			}
			HighScoresScreen highScoresScreen = new HighScoresScreen(game);
			highScoresScreen.setYourScore(mp.getScore());
			game.setScreen(highScoresScreen);
		}

	}

	@Override
	public void paint(float deltaTime) {
		Graphics g = game.getGraphics();
		g.clearScreen(Color.BLACK);
		g.drawImage(Assets.menuBackground, 0, -300);
		if (!gameOver) {
			// //////////////draw here//////////////////////////
			if (getPlayingMode() == PlayingMode.SINGLE) {

				// Objects
				c.draw(g);
				// if (this.getNinja().getY() > )
				// building proper display for enemies!
				sb.draw(g);
				mp.draw(g);
				// weapons.draw(g);

				c.draw1(g);// I added to see robot swing! how to fix this
			}
			for (GameButton b : buttons) {
				b.paint(deltaTime);
			}
		} else if (gameOver) {

			// SHOW SCORE
			/*
			 * if (win) { // Score// Font fnt0 = new Font("arial", Font.PLAIN,
			 * 50); g.setFont(fnt0); g.setColor(Color.yellow);
			 * g.drawString("YOU WON!!", WIDTH / 3, 250); g.drawString("SCORE:"
			 * + Integer.toString(mp.getScore()), WIDTH / 3, 350);
			 */
			// } else if (!win)
			{
				Paint p = new Paint();
				p.setTextSize(50);
				p.setColor(Color.GREEN);
				p.setTypeface(Assets.fontFace);
				g.drawString("Your Score!!", WIDTH / 3, 250, p);
				g.drawString("SCORE:" + Integer.toString(mp.getScore()), WIDTH / 3, 350, p);
			}
		}
		Paint p = new Paint();
		p.setTextSize(50);
		p.setTypeface(Assets.fontFace);
		if (time.getLevel() == 1) {
			p.setColor(Color.BLUE);
		} else if (time.getLevel() == 2) {
			p.setColor(Color.rgb(255, 140, 0));
		} else if (time.getLevel() == 3) {
			p.setColor(Color.RED);
		}

		p.setTextAlign(Align.CENTER);
		g.drawString("Level " + time.getLevel(), NinjaGame.WIDTH / 2, 60, p);
		p.setTextSize(30);
		p.setColor(Color.BLUE);
		g.drawString(String.format("Time: %.2f s", ((System.currentTimeMillis() - time.getStartTime()) / 1000f)),
				NinjaGame.WIDTH - 200, 40, p);
		p.setColor(Color.DKGRAY);
		g.drawString(playerName, NinjaGame.WIDTH / 2, 90, p);
	}

	@Override
	public void pause() {
		try {
			Assets.theme.pause();
		} catch (Exception ex) {

		}
		final AndroidGame _game = (AndroidGame) game;
		_game.runOnUiThread(new Runnable() {

			@Override
			public void run() {
				_game.setAdVisibility(true);
			}
		});
	}

	@Override
	public void resume() {
		final AndroidGame _game = (AndroidGame) game;
		_game.runOnUiThread(new Runnable() {

			@Override
			public void run() {
				_game.setAdVisibility(false);
			}
		});
		try {
			Assets.theme.play();
		} catch (Exception ex) {

		}
	}

	@Override
	public void dispose() {
	}

	@Override
	public void backButton() {
		new AlertDialog.Builder((NinjaGame) game).setMessage("Current progress will be lost! Continue?")
				.setPositiveButton("OK", new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						game.setScreen(new MainMenuScreen(game));
					}
				}).setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {

					}
				}).setCancelable(false).create().show();

	}

	@Override
	public void onExecute(GameButton button) {
	}

	@Override
	public void onPressed(GameButton button) {
		KeyEvent event = new KeyEvent();
		event.setKeyCode(button.getKeyCode());
		keyPressed(event);
	}

	@Override
	public void onRealeased(GameButton button) {
		KeyEvent event = new KeyEvent();
		event.setKeyCode(button.getKeyCode());
		keyReleased(event);
	}

	public int getEnemy_count() {
		return enemy_count;
	}

	public void setEnemy_count(int enemy_count) {
		this.enemy_count = enemy_count;
	}

	public int getEnemy_killed() {
		return enemy_killed;
	}

	public void setEnemy_killed(int enemy_killed) {
		this.enemy_killed = enemy_killed;
	}

	public MyNinja getNinja() {
		return this.mp;
	}

	public MyNinja getNinja2() {
		return this.mp2;
	}

	public int getTotalKilled() {
		return totalKilled;
	}

	public void setTotalKilled(int totalKilled) {
		this.totalKilled = totalKilled;
	}

	public boolean isGameOver() {
		return gameOver;
	}

	public void setGameOver(boolean gameOver) {
		this.gameOver = gameOver;
	}

	public void setWin(boolean n) {
		win = n;
	}

	public int getCombo() {
		return combo;
	}

	public void setJumping(boolean jumping) {
		this.jumping = jumping;
	}

	public void setthrowing(boolean throwing) {
		this.throwing = throwing;
	}

	public void setWeapon(boolean weapon) {
		this.weapon = weapon;
	}

	public void setEnemy_Spawn(boolean enemy_spawn) {
		this.enemy_spawn = enemy_spawn;
	}

	public boolean getBuilding_Block() {
		return this.building_Block;
	}

	public boolean getTree_Block() {
		return this.tree_Block;
	}

	public boolean getRoad_Block() {
		return this.road_Block;
	}

	public void setBossSpawn(boolean bossSpawn) {
		this.bossSpawn = bossSpawn;

	}

	public void setPlayerName(String value) {
		this.playerName = value;
	}

}
